#include <audio/MIDI/MIDIOutDeviceWin32.h>
#include <system/Log.h>

#if NE_PLATFORM == NE_PLATFORM_WINDOWS

namespace ne
{
    MIDIOutDeviceWin32::MIDIOutDeviceWin32(const uint32_t id, const std::string &name)
        : MIDIOutDevice(id, name)
    {
        _create();
    }

    bool MIDIOutDeviceWin32::open()
    {
        if (isOpen()) return true;

        MIDIOUTCAPS outCaps;
        for (uint32_t i=0; i<midiOutGetNumDevs(); ++i)
        {
            midiOutGetDevCaps(i, &outCaps, sizeof(MIDIOUTCAPS));
            Log::Out("MIDI OUT CAPS[%d, %s]", i, outCaps.szPname);
        }
        midiOutOpen(&mOutDeviceHandle, mID, 0, 0, CALLBACK_NULL);
        Log::Out("MIDIOutDeviceWin32[0x%x]", mOutDeviceHandle);
        mIsOpen = true;

        return true;
    }

    bool MIDIOutDeviceWin32::reset()
    {
        midiOutReset(mOutDeviceHandle);
        return true;
    }

    bool MIDIOutDeviceWin32::close()
    {
        if (!isOpen()) return true;

        midiOutClose(mOutDeviceHandle);
        mIsOpen = false;

        return false;
    }

    bool MIDIOutDeviceWin32::sendEvent(const byte event, const byte parameter1, const byte parameter2)
    {
        DWORD dwMsg = event | (parameter1 << 8) | (parameter2 << 16);
        MMRESULT result = midiOutShortMsg(mOutDeviceHandle, dwMsg);
        if (result != MMSYSERR_NOERROR)
        {
            Log::Out(LL_WARNING, "MIDIOutDeviceWin32::sendEvent Error");
            return false;
        }
        return true;
    }

    bool MIDIOutDeviceWin32::sendSysExEvent(const byte *buffer, const uint32_t length)
    {
        /*
        MMRESULT result = midiOutLongMsg(mOutDeviceHandle, buffer, length);
        if (result != MMSYSERR_NOERROR)
        {
            Log::Out(LL_WARNING, "MIDIOutDeviceWin32::sendSysExEvent Error");
            return false;
        }
        */
        return true;
    }

    MIDIOutDeviceWin32::~MIDIOutDeviceWin32()
    {
        _destroy();
    }

    bool MIDIOutDeviceWin32::_create()
    {
        return true;
    }

    bool MIDIOutDeviceWin32::_destroy()
    {
        return close();
    }
}

#endif
